<?php

namespace control;

//管理员后台-库存余额
class inventoryBalanceClass extends adIndexClass
{
    private const title      = '库存余额表';
    private const page       = 'inventoryBalance';
    private const table      = 'inventory_record';
    private const tableInv   = 'inventory';
    private const tableInvMx = 'inventory_detail';
    private const warning    = ['无', '低', '中', '高'];

    /**
     * 字段初始化
     */
    public function fieldInit($fun): array
    {
        switch ($fun) {
            default:
                $tr = [
                    'code'              => [
                        'name'  => '{l.inventoryBalance.homeSearch.code}',
                        'width' => 150,
                        'sort'  => 1,
                    ],
                    'name'              => [
                        'name'  => '{l.inventoryBalance.homeSearch.materialName}',
                        'width' => 150,
                        'sort'  => 1,
                    ],
//                    'typeName'          => [
//                        'name'  => '{l.inventoryBalance.homeSearch.materialType}',
//                        'width' => 150,
//                    ],
//                    'model'             => [
//                        'name'  => '{l.inventoryBalance.homeSearch.model}',
//                        'width' => 150,
//                    ],
                    'unit'              => [
                        'name'  => '{l.inventoryBalance.homeSearch.unit}',
                        'width' => 60,
                    ],
                    'num'               => [
                        'name'  => '重量',
                        'width' => 100,
                        'sort'  => 1,
                    ],
//                    'checkNum'          => [
//                        'name'  => '{l.inventoryBalance.homeSearch.checkNum}',
//                        'width' => 100,
//                        'sort'  => 1,
//                    ],
//                    'defectiveQuantity' => [
//                        'name'  => '{l.inventoryBalance.homeSearch.defectiveQuantity}',
//                        'width' => 100,
//                    ],
//                    'unit_one'          => [
//                        'name'  => '{l.inventoryBalance.homeSearch.unit_one}',
//                        'width' => 60,
//                    ],
//                    'unitOneNum'        => [
//                        'name'  => '{l.inventoryBalance.homeSearch.unitOneNum}',
//                        'width' => 100,
//                    ],
//                    'unit_two'          => [
//                        'name'  => '{l.inventoryBalance.homeSearch.unit_two}',
//                        'width' => 60,
//                    ],
//                    'unitTwoNum'        => [
//                        'name'  => '{l.inventoryBalance.homeSearch.unitTwoNum}',
//                        'width' => 100,
//                    ],
                    'unitPrice'         => [
                        'name'  => '{l.inventoryBalance.homeSearch.unitPrice}（' . static::$unit . '）',
                        'width' => 100,
                    ],
                    'money'             => [
                        'name'  => '{l.inventoryBalance.homeSearch.money}（' . static::$unit . '）',
                        'width' => 100,
                    ],
//                    'inventoryAlert'    => [
//                        'name'  => '{l.inventoryBalance.homeSearch.inventoryAlert}',
//                        'width' => 100,
//                    ]
                    'start_position' => [
                        'name'  => '起始液位',
                        'width' => 100,
                    ],
                    'end_position' => [
                        'name'  => '截止位置',
                        'width' => 100,
                    ],
                    'time' => [
                        'name' => '时间',
                        'width' => 100,
                    ],
                ];
        }
        return $tr;
    }

    /*列表页-查询条件*/
    public function homeOptions($isAsync = true)
    {
        $result = sqlFind("SELECT id, name FROM `warehouse` WHERE coid = '" . self::$coid . "' AND state = '启用' " . self::getWarehouseSql());
        $value  = [];
        foreach ($result as $v) {
            $value[$v['id']] = $v['name'];
        }
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    L('inventoryBalance.home.warehouse') => checkbox([
                        "name"    => "warehouse",
                        "value"   => $value,
                        'checked' => '',
                    ]),
                ],
                [
                    L('inventoryBalance.home.code')         => text(array("name" => "code")),
                    L('inventoryBalance.home.materialName') => text(array("name" => "materialName")),
                    L('inventoryBalance.home.model')        => text(array("name" => "model")),

                ],
                [
                    L('inventoryBalance.home.warning') => select(["name" => "warning", 'option' => [1 => L('inventoryBalance.inventoryAlert.not'), 2 => L('inventoryBalance.inventoryAlert.low'), 3 => L('inventoryBalance.inventoryAlert.center'), 4 => L('inventoryBalance.inventoryAlert.height')]]),
                    L('inventoryBalance.home.typeId')  => materialClass::typeSelect(name: 'typeId', title: '请选择'),
                ]
            ]
        ], 1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    /**
     * 查询条件
     *
     * @return string
     */
    public function home(): string
    {
        $html = $this->homeOptions(false);
        //控件
        $button = "";
        if ($this->power(self::page, "export")) {
            $button .= "<span class='spanButton' onclick=\"layer('importTemplate','exportFrame',{cla:'" . self::page . "'})\">导出</span>";
        }
        //返回
        return $this->homeFun($this->search($html, layout: 'pop', toolButton: $button));
    }

    /*列表页-查询结果*/
    public function homeSearch(): string
    {
        //查询结果
        $where = " a.coid = '" . self::$coid . "' ";
        // 仓库
        $warehouseId = '';
        if ($this->post('warehouse')) {
            $warehouseId = " AND warehouseId in ('" . implode("','", $this->post('warehouse')) . "')";
            $where       .= " AND a.warehouseId in ('" . implode("','", $this->post('warehouse')) . "')";
        } else {
            $where .= self::getWarehouseSql('a.warehouseId');
        }
        $where .= search([
            "like" => [
                'b.code'  => $this->post('code'),
                'b.name'  => $this->post('materialName'),
                'b.model' => $this->post('model'),
            ],
        ]);
        if ($this->post('typeId')) {
            $allTypeId = materialClass::getAllChildTypeId($this->post('typeId'));
            $where     .= " and b.typeId in ('" . implode("','", $allTypeId) . "')";
        }
        $fieldArr     = self::resolveField([
            'field' => 'a.`inventoryMxId` ,a.`id`, a.`coid`, a.`warehouseId`, a.`materialId`, SUM(a.num) as num, a.`time`, b.`downStock`, b.`upStock`, b.`unit_one`, b.`unit_two`, b.`unit_one_num`, b.`unit_two_num`, b.`code`, b.`name`, b.`typeName`, b.`model`, b.`unit`',
            'group' => 'a.materialId',
        ]);
        $outAllowZero = optionSettingClass::getSettingItem('库存', 'outAllowZero');//允许零库存出库
        $having       = "";
        if (!$outAllowZero) {
            $having = " HAVING `num` > 0 ";
        }
        switch ($this->post('warning')) {
            case 1:
                $where .= " and b.upStock = '-1' and b.downStock = '-1' ";
                break;
            case 2:
                $having .= $having ? " and " : " HAVING ";
                $having .= " downStock != '-1' and `num` < downStock ";
                break;
            case 3:
                $having .= $having ? " and " : " HAVING ";
                $having .= " not ( upStock = '-1' and  downStock = '-1') and not (downStock != '-1' and `num` < downStock) and not(upStock != '-1' and `num` > upStock)";
                // $having .= " ((downStock != '-1' and `num` >= downStock) or (upStock != '-1' and `num` <= upStock)) ";
                break;
            case 4:
                $having .= $having ? " and " : " HAVING ";
                $having .= " upStock != '-1' and `num` > upStock ";
                break;
        }
        //排序
        $orderBy                             = $this->listSort(array(
            "search" => $this->post('list_sort_key') ?: 'code',
            "sort"   => $this->post('list_sort') ?: "desc",
            "array"  => array(),
        ));
        $page                                = $this->page([
            "table" => "material as b left join ".self::table." as a on a.materialId = b.id",
            'field' => $fieldArr['field'],
            "where" => $where . $fieldArr['group'] . $having,
            "order" => $orderBy['orderBy']
        ]);
        $json['sql']                         = $page['sql'];
        $_SESSION[self::page]['sql']         = $page['sql'];
        $_SESSION[self::page]['warehouseId'] = $warehouseId;
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array("");
        //获取记录
        $url = root . "control/adIndex.html?cla=" . self::page;
        //获取记录
        foreach ($page['array'] as $array) {
            //列表控件
            $dominate = [
                "detail" => array(
                    "title" => L('inventoryBalance.homeSearch.detail'),
                    "click" => "newIframe('" . L('inventoryBalance.homeSearch.detail') . "','" . $url . "&fun=detail&id=" . $array['materialId'] . "')",
                ),
            ];
            // 库存单价
            $unitPrice  = $this->power(self::page, "price") ? self::lostZero(self::unitPrice($array['materialId']),'pricePrecision') : '**';
            $money      = $this->power(self::page, "price") ? self::formattingFigure($unitPrice * $array['num']) : '**';
            $liButton[] = $this->dominate($dominate);
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case 'num':
                        $row[] = self::lostZero($array['num'], 'numPrecision');
                        break;
                    case 'checkNum':
                        $row[] = self::pendingCheck($array['materialId'], $warehouseId);
                        break;
                    case 'defectiveQuantity':
                        $row[] = self::unhealthy($array['materialId'], $array['unit'], $warehouseId);
                        break;
                    case 'unitOneNum':
                        $unitOneNum = empty((float)$array['unit_one_num']) || !$array['unit_one'] ? '' : self::formattingFigure($array['num'] / $array['unit_one_num'], 'numPrecision');
                        $row[]      = $unitOneNum;
                        break;
                    case 'unitTwoNum':
                        $unitTwoNum = empty((float)$array['unit_two_num']) || !$array['unit_two'] ? '' : self::formattingFigure($array['num'] / $array['unit_two_num'], 'numPrecision');
                        $row[]      = $unitTwoNum;
                        break;
                    case 'unitPrice':
                        $row[] = $unitPrice;
                        break;
                    case 'money':
                        $row[] = $money;
                        break;
                    case 'inventoryAlert':
                        $inventoryAlert = self::inventoryAlert((float)$array['upStock'], (float)$array['downStock'], (float)$array['num']);
                        $row[]          = $inventoryAlert;
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        $totalQuery = find([
            'table'  => self::table . " as a join material as b on a.materialId = b.id",
            'single' => $where,
            'field'  => "ifnull(sum(a.num),0) as num,ifnull(sum(a.num/b.unit_one_num),0) as unitOneNum,ifnull(sum(a.num/b.unit_two_num),0) as unitTwoNum,ifnull(sum(a.num*a.defaultPrice),0) as money",
        ]);
        // 待检数
        $pendingCheckQuery = find([
            'table'  => "quality_order as qo join material as mat on qo.materialId = mat.id",
            'single' => " qo.state = '待质检' and qo.type not in (6,3,4) {$warehouseId} and qo.materialId in (select a.materialId from " . self::table . " as a join material as b on a.materialId = b.id where {$where}) ",
            'field'  => " ifnull(SUM(CASE WHEN qo.unit = mat.unit_one THEN qo.num*mat.unit_one_num WHEN qo.unit = mat.unit_two THEN qo.num*mat.unit_two_num ELSE qo.num END),0) AS num",
        ]);
        // 不良数
        $defectiveQuantity = find([
            'table'  => "quality_order as q, quality_order_reason as r, material as mat",
            'single' => " q.type <> 3 and q.id = r.orderId and q.materialId = mat.id and q.coid = '".self::$coid."' and q.state = '已质检' and r.state = '待处理' {$warehouseId} and q.materialId in (select a.materialId from " . self::table . " as a join material as b on a.materialId = b.id where {$where}) ",
            'field'  => " ifnull(SUM(CASE WHEN q.unit = mat.unit_one THEN r.num*mat.unit_one_num WHEN q.unit = mat.unit_two THEN r.num*mat.unit_two_num ELSE r.num END),0) AS num",
        ]);
        $total    = [
            'money'        => self::formattingFigure($totalQuery['money']),
            'num'        => self::formattingFigure($totalQuery['num'], 'numPrecision'),
            'unitOneNum'   => self::formattingFigure($totalQuery['unitOneNum'], 'numPrecision'),
            'unitTwoNum' => self::formattingFigure($totalQuery['unitTwoNum'], 'numPrecision'),
            'checkNum' => self::formattingFigure($pendingCheckQuery['num'], 'numPrecision'),
            'defectiveQuantity' => self::formattingFigure($defectiveQuantity['num'], 'numPrecision'),
        ];
        //生成页面
        $li = $this->li(array(
            "body"        => $body,
            "install"     => $installSearch,
            "button"      => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page"        => $page['para'],
            "total"       => $total,
        ));
        //返回
        $json['html'] = "<form name='listForm'>" . $li . "</form>" . $page['button'];
        return json_encode($json, 320);
    }

    /**
     * 库存预警
     *
     * @param float $up
     * @param float $down
     * @param float $now
     * @return string
     */
    public static function inventoryAlert(float $up, float $down, float $now): string
    {
        if ($up < $now && $up != -1) {
            return L('inventoryBalance.inventoryAlert.height');
        } elseif ($down > $now && $down != -1) {
            return L('inventoryBalance.inventoryAlert.low');
        } else if ($up == -1 && $down == -1) {
            return L('inventoryBalance.inventoryAlert.not');
        } else {
            return L('inventoryBalance.inventoryAlert.center');
        }
    }

    /** 最低最高库存控制
     *
     * @param       $materialId
     * @param float $quantity 主单位数量
     * @param       $type     down 低库存出库限制，top 高库存入库限制
     * @return mixed
     */
    public static function inventoryControl($materialId, float $quantity, $type = 'down'): mixed
    {
        if (empty($materialId)) {
            return L('inventoryBalance.inventoryControl.missingParameter');
        }
        $parameters         = optionSettingClass::getSetting('库存');
        $inventoryStockWarn = $parameters['inventoryStockWarn'];  //最高最低库存预警包含不参与可用量仓库
        $inventoryStockCtrl = $parameters['inventoryStockCtrl'];  //最低最高库存控制
        $where              = '';
        if (!$inventoryStockWarn) {
            //参与MRP运算仓库
            $mrpWarehouse = (array)$parameters['mrpWarehouse'];
            $where        .= " and warehouseId in ('" . implode("','", $mrpWarehouse) . "') ";
        }
        $material = query('material', "id = '$materialId'", "name,unit,upStock,downStock");
        $num      = find(array('table' => 'inventory_record', 'where' => "coid = '" . self::$coid . "' and materialId = '$materialId'" . $where, 'sum' => "num"));
        switch ($type) {
            case 'top':
                $warn = $material['upStock'] != -1 && $num + $quantity > $material['upStock'] ? str_replace(['{{materialName}}', '{{upStock}}'], [$material['name'], $material['upStock']], L('inventoryBalance.inventoryControl.upStock')) : true;
                break;
            case 'down':
                $warn = $material['downStock'] != -1 && $num - $quantity < $material['downStock'] ? str_replace(['{{materialName}}', '{{upStock}}'], [$material['name'], $material['downStock']], L('inventoryBalance.inventoryControl.downStock')) : true;
                break;
            default:
                $warn = '未知类型';
        }
        //发送预警消息，提示
        if (!$inventoryStockCtrl && $warn !== true) {
            $settingId = $type == 'top' ? 'inventoryToplimit' : 'inventoryFloor';
            $setting   = self::getSettingValue($settingId);
            foreach ($setting['member'] as $item) {
                $text = match ($type) {
                    'top' => str_replace(['{{materialName}}'], [$material['name']], L('inventoryBalance.inventoryControl.upStockText')),
                    'down' => str_replace(['{{materialName}}'], [$material['name']], L('inventoryBalance.inventoryControl.downStockText')),
                };
                message(array(
                    "stid"      => $item,
                    "type"      => '预警消息',
                    "typeId"    => $materialId,
                    "text"      => $text,
                    "targetCla" => 'inventoryBalance',
                    "targetFun" => 'home',
                ));
            }
            return true;
        }
        return $warn;
    }

    /** 详情页
     *
     * @return string
     */
    public function detail(): string
    {
        $info = query('material', " id = '{$this->get('id')}' ");
        if (empty($info['id'])) {
            $html = L('inventoryBalance.detail.empty');
        } else {

            //菜单
            $data      = array(
                "id" => $info['id'],
            );
            $total     = self::inventoryNum($info['id']);
            $unitPrice = self::unitPrice($info['id']);

            $unitOneNum = empty((float)$info['unit_one_num']) || !$info['unit_one'] ? '' : round($total / $info['unit_one_num'], 2);
            $unitTwoNum = empty((float)$info['unit_two_num']) || !$info['unit_two'] ? '' : round($total / $info['unit_two_num'], 2);

            $outAllowZero = optionSettingClass::getSettingItem('库存', 'outAllowZero');//允许零库存出库
            $having       = "";
            if (!$outAllowZero) {
                $having = " HAVING `num` > 0 ";
            }
            $warehouseTr[] = ['{l.inventoryBalance.detail.warehouse}', '{l.inventoryBalance.detail.mainUnit}', '{l.inventoryBalance.detail.unitNum}', '{l.inventoryBalance.detail.unit_one}', '{l.inventoryBalance.detail.unitOneNum}', '{l.inventoryBalance.detail.unit_two}', '{l.inventoryBalance.detail.unitTwoNum}'];

            $fieldArr = self::resolveField([
                'field' => 'warehouseId, materialId, sum(num) as num, batch ',
                'group' => 'warehouseId',
            ]);
            $result   = find([
                'field' => $fieldArr['field'],
                'table' => self::table,
                'where' => generateWhere([
                        'materialId' => $info['id'],
                        'coid'       => self::$coid,
                    ]) . $fieldArr['group'] . $having . " ORDER by num",
            ]);
            $totalArr = ['num'=>0,'unit_one'=>0,'unit_two'=>0];
            foreach ($result['array'] as $array) {
                $unitNum       = $array['num'];
                $unitOneNumMx  = empty((float)$info['unit_one_num']) || !$info['unit_one'] ? 0 : self::formattingFigure($unitNum / $info['unit_one_num'], 'numPrecision');
                $unitTwoNumMx  = empty((float)$info['unit_two_num']) || !$info['unit_two'] ? 0 : self::formattingFigure($unitNum / $info['unit_two_num'], 'numPrecision');
                $warehouseTr[] = [warehouseClass::getName($array['warehouseId']), $info['unit'], self::formattingFigure($array['num'], 'numPrecision'), $info['unit_one'], self::lostZero($unitOneNumMx, 'numPrecision'), $info['unit_two'], self::lostZero($unitTwoNumMx, 'numPrecision')];
                $totalArr['num'] += $array['num'];
                $totalArr['unit_one'] += $unitOneNumMx;
                $totalArr['unit_two'] += $unitTwoNumMx;
            }
            $warehouse_tr = [
                2=>self::lostZero($totalArr['num'],'numPrecision'),
                4=>self::lostZero($totalArr['unit_one'],'numPrecision'),
                6=>self::lostZero($totalArr['unit_two'],'numPrecision'),
            ];

            $inventoryTr[] = ['{l.inventoryBalance.detail.warehouseName}', '{l.inventoryBalance.detail.location}', '{l.inventoryBalance.detail.batch}', '{l.inventoryBalance.detail.unit}', '{l.inventoryBalance.detail.num}', '{l.inventoryBalance.detail.price}', '{l.inventoryBalance.detail.money}'];
            $where         = " 1=1 and materialId = '$info[id]' and coid = '" . self::$coid . "' ";
            $fieldArr      = self::resolveField([
                'field' => '`id`, `coid`, `warehouseId`, `positionId`,inventoryMxId, batch, SUM(num) as num, min(time) as time',
                'group' => 'warehouseId,positionId,batch',
            ]);
            $where         .= $fieldArr['group'];
            $result        = find([
                'table' => self::table,
                'field' => $fieldArr['field'],
                'where' => $where . $having . " order by time",
            ]);
            $totalArr = ['num'=>0,'money'=>0];
            foreach ($result['array'] as $array) {
                $record           = query("inventory_record", " warehouseId = '$array[warehouseId]' and positionId = '$array[positionId]' and materialId = '$info[id]' and batch = '$array[batch]' and num > 0 ", "inventoryMxId");
                $inventory_detail = query('inventory_detail', " id = '$record[inventoryMxId]' ", "price");
                $money            = self::formattingFigure($array['num'] * (float)$inventory_detail['price']);
                $inventoryTr[]    = [warehouseClass::getName($array['warehouseId']), warehousePositionClass::getName($array['positionId']), $array['batch'], $info['unit'], self::lostZero($array['num'], 'numPrecision'), self::lostZero($inventory_detail['price'], 'pricePrecision'), self::lostZero($money)];
                $totalArr['num'] += $array['num'];
                $totalArr['money'] += $money;
            }
            $inventory_tr = [
                4=>self::lostZero($totalArr['num'],'numPrecision'),
                6=>self::lostZero($totalArr['money']),
            ];
            //生成表单
            $data['html'] = $this->tableShow([
                '详细信息' => [
                    [
                        L('inventoryBalance.detail.type') => $info['typeName'],
                        L('inventoryBalance.detail.code') => $info['code'],
                        L('inventoryBalance.detail.name') => $info['name'],
                        L('inventoryBalance.detail.model')    => $info['model'],
                    ],
                    [
                        L('inventoryBalance.detail.mainUnit') => $info['unit'],
                        L('inventoryBalance.detail.unit_one') => $info['unit_one'],
                        L('inventoryBalance.detail.unitOneNum') => self::lostZero($unitOneNum, 'numPrecision'),
                        L('inventoryBalance.detail.unit_two')   => $info['unit_two'],
                    ],
                    [
                        L('inventoryBalance.detail.unitTwoNum') => self::lostZero($unitTwoNum, 'numPrecision'),
                        L('inventoryBalance.detail.inventoryTotal') => self::lostZero($total, 'numPrecision'),
                        L('inventoryBalance.detail.price')          => self::lostZero($unitPrice, 'pricePrecision'),
                        L('inventoryBalance.detail.money')          => self::formattingFigure($total * $unitPrice),
                    ],
                ],
            ]);
            $data['html'] .= $this->detailList([
                'title' => L('inventoryBalance.detail.warehouseTotal'),
                'html' => $this->listTable(array('tr' => $warehouseTr, 'showEmpty' => true, 'showSort' => true, 'total' => $warehouse_tr)),
            ]);
            $data['html'] .= $this->detailList([
                'title' => L('inventoryBalance.detail.inventoryMx'),
                'html' => $this->listTable(array('tr' => $inventoryTr, 'showEmpty' => true, 'showSort' => true, 'total' => $inventory_tr)),
            ]);
            //生成页面
            $html = $this->tab($data);
        }
        //返回
        return $html;
    }


    /**
     * 导出
     */
    public function exportData()
    {
        $templateId     = $this->get('templateId');
//        $checkedId = $this->get('checkedId')?explode(',',$this->get('checkedId')):[];
        if (!$this->power(self::page, 'export')) {
            $_SESSION['warn'] = L('inventoryBalance.exportData.power');
        } else {
            $warehouseId = $_SESSION[self::page]['warehouseId'];
            $data        = [];
            /***********标题**********/
            $title        = [];
            $tempFieldAll = importTemplateClass::templateField(self::page, 'exportFieldInit', id:$templateId);
            foreach ($tempFieldAll as $array) {
                if ($array['display']) {
                    $title[] = $array['aliasName'];
                }
            }
            $sql    = $_SESSION[self::page]['sql'];
            $result = sqlFind($sql);
            //导出数据生成
            foreach ($result as $array) {
                $column     = [];
                $unitNum    = $array['num'];
                $unitOneNum = empty((float)$array['unit_one_num']) ? '' : self::formattingFigure($unitNum / $array['unit_one_num'], 'numPrecision');
                $unitTwoNum = empty((float)$array['unit_two_num']) ? '' : self::formattingFigure($unitNum / $array['unit_two_num'], 'numPrecision');
                // 库存单价
                $unitPrice      = self::unitPrice($array['materialId']);
                $inventoryAlert = self::inventoryAlert((float)$array['upStock'], (float)$array['downStock'], (float)$array['num']);
                foreach ($tempFieldAll as $templateField) {
                    if ($templateField['display']) {
                        $column[] = match ($templateField['columnName']) {
                            '物料编码' => $array['code'],
                            '物料名称' => $array['name'],
                            '物料分类' => $array['typeName'],
                            '规格型号' => $array['model'],
                            '主单位' => $array['unit'],
                            '主单位数量' => self::lostZero($unitNum, 'numPrecision'),
                            '待检数量' => self::pendingCheck($array['materialId'], $warehouseId),
                            '不良数量' => self::unhealthy($array['materialId'], $array['unit'], $warehouseId),
                            '辅单位1' => $array['unit_one'],
                            '辅单位1数量' => self::lostZero($unitOneNum, 'numPrecision'),
                            '辅单位2' => $array['unit_two'],
                            '辅单位2数量' => self::lostZero($unitTwoNum, 'numPrecision'),
                            '单价' => self::lostZero($unitPrice, 'pricePrecision'),
                            '金额' => self::formattingFigure($unitPrice * $unitNum),
                            '库存预警' => $inventoryAlert,
                            default => '',
                        };
                    }
                }
                $data[] = $column;
            }
            $text = str_replace(['{{staffName}}'], [$this->control['name']], L('inventoryBalance.exportData.log'));
            $this->logText(["type" => self::page, "text" => $text]);
            $this->excelOut($title, $data, L('inventoryBalance.exportData.fileName') . ".xlsx");
            exit(0);
        }
        header("Location:" . getenv("HTTP_REFERER"));

    }

    /**
     * 库存单价
     *
     * @param string $materialId
     * @return float
     */
    public static function unitPrice(string $materialId): float
    {
        $inventory_price = query("inventory_price", " coid = '" . self::$coid . "' and materialId = '" . $materialId . "' order by id desc ", 'avgPrice');
        return floatval($inventory_price['avgPrice']);
    }

    /**
     * 出、入库单价
     *
     * @param string $materialId
     * @param string $warehouseId
     * @param string $classify
     * @param string $and
     * @return float
     */
    public static function inOutUnitPrice(string $materialId, string $warehouseId, string $classify, string $and = ''): float
    {
        $and .= ($classify == '入库') ? " and state in ('已入库','已复核') " : " and state in ('已出库','已复核') ";
        return self::formattingFigure(static::total([
            'sql'   => "SELECT IFNULL(SUM(d.money)/SUM(d.num), 0) as total FROM `inventory_changes_detail` as d, inventory_changes as i WHERE d.orderId = i.id " . $and,
            'where' => [
                'd.materialId'  => $materialId,
                'd.warehouseId' => $warehouseId,
                'i.classify'    => ($classify == '入库') ? 1 : 0,
                'd.coid'        => self::$coid,
            ],
        ]), 'pricePrecision');
    }

    /**
     * 出、入库数量
     *
     * @param string $materialId
     * @param string $warehouseId
     * @param string $classify
     * @param string $and
     * @return float
     */
    public static function inOutUnitNum(string $materialId, string $warehouseId = '', string $classify = '入库', string $and = ''): float
    {
        $and .= ($classify == '入库') ? " and state in ('已入库','已复核') " : " and state in ('已出库','已复核') ";
        return self::formattingFigure(static::total([
            'sql'   => "SELECT IFNULL(SUM(d.num), 0) as total FROM `inventory_changes_detail` as d, inventory_changes as i WHERE d.orderId = i.id " . $and,
            'where' => [
                'd.materialId'  => $materialId,
                'd.warehouseId' => $warehouseId,
                'i.classify'    => ($classify == '入库') ? 1 : 0,
                'd.coid'        => self::$coid,
            ],
        ]), 'numPrecision');
    }


    /** 库存数量
     *
     * @param string $materialId 物料Id
     * @param string $warehouseId 仓库id
     * @param string|bool $positionId 库位id  false代表查询不加入此条件（可以兼容查询字段为空的情况）
     * @param string|bool $batch 批次  false代表查询不加入此条件
     * @param string $unit 单位 不传默认主单位
     * @return float
     */
    public static function inventoryNum(string $materialId, string $warehouseId = '', string|bool $positionId = false, string|bool $batch = false, string $unit = ''): float
    {
        $where = [
            'materialId' => $materialId,
            'coid'       => static::$coid,
        ];
        if ($warehouseId) {
            $where['warehouseId'] = $warehouseId;
        }
        if ($positionId !== false) {
            $where['positionId'] = $positionId;
        }
        if ($batch !== false) {
            $where['batch'] = $batch;
        }
        $inventoryNum = static::total([
            'sql'   => 'SELECT IFNULL(sum(num), 0) as total FROM `inventory_record`',
            'where' => $where,
        ]);
        // 单位转换
        if($unit){
            $material = query('material', " id = '$materialId'","id,unit_one,unit_one_num,unit_two,unit_two_num");
            return match ($unit) {
                $material['unit_one'] => floatval($material['unit_one_num']) > 0 ? self::formattingFigure($inventoryNum/floatval($material['unit_one_num']),'num') : $inventoryNum,
                $material['unit_two'] => floatval($material['unit_two_num']) > 0 ? self::formattingFigure($inventoryNum/floatval($material['unit_two_num']),'num') : $inventoryNum,
                default => $inventoryNum,
            };
        }
        return $inventoryNum;
    }

    /** 匹配仓位
     *
     * @param mixed $warehouseId
     * @return string
     */
    public static function matchLocation(mixed $warehouseId = ''): string
    {
        $warehouse_position = query("warehouse_position", " orderId = '" . $warehouseId . "' and isDefault = 1 ", "id"); //默认仓位
        $positionId         = $warehouse_position['id'];
        $optionSetting      = optionSettingClass::getSetting('库存');  //选项设置
        if ($optionSetting['warehousePosition']['option'] && $optionSetting['warehousePosition']['auto'] && $optionSetting['warehousePosition']['method'] == 'material') {
            $where            = "";
            $and              = " AND coid = '" . self::$coid . "' ";
            $like             = [];
            $equal            = [
                'warehouseId' => $warehouseId,
            ];
            $where            .= search([
                    "like" => $like,
                    "="    => $equal,
                ]) . $and;
            $fieldArr         = self::resolveField([
                'field' => '`positionId`, SUM(num) as num',
                'group' => 'positionId,materialId',
            ]);
            $where            .= $fieldArr['group'] . " having sum(num)>0";
            $inventory_record = find(["table" => 'inventory_record', 'field' => $fieldArr['field'], "single" => $where . " order by num desc limit 1"]);
            if (isset($inventory_record['positionId']) && $inventory_record['positionId']) {
                $positionId = $inventory_record['positionId'];
            }
        }
        return $positionId;
    }

    /** 记录库存到库位
     *
     * @param string $inId 入库记录id
     * @param array $data ['materialId'=>'物料Id','warehouseId'=>'仓库id','positionId'=>'库位id','batch'=>'批次']
     * @return mixed
     */
    public static function recordStockToLocation(string $inId = '', array $data = []): mixed
    {
        $warn               = true;
        $warehouse_position = query("warehouse_position", " id = '$data[positionId]' ");
        if (empty($warehouse_position['id'])) {
            $warn = L('inventoryBalance.recordStockToLocation.none');
            goto resp;
        }
        $inventoryRecordId = (array)explode(',', $warehouse_position['inventoryRecordId']);
        if (!empty($inId)) {
            $inventoryRecordId[] = $inId;
        } else {
            $inventoryNum = inventoryBalanceClass::inventoryNum($data['materialId'], $data['warehouseId'], $warehouse_position['id'], $data['batch']);
            //库存出完后，清除该批次在对应仓位的id
            if ($inventoryNum <= 0) {
                $result            = self::sqlFind(" SELECT id FROM `inventory_record` WHERE materialId = '" . $data['materialId'] . "' and warehouseId = '" . $data['warehouseId'] . "' and positionId = '" . $warehouse_position['id'] . "' and batch = '" . $data['batch'] . "' and num > 0 ");
                $ids               = array_column((array)$result, 'id');                         //该批次对应的所有入库id
                $inventoryRecordId = array_values((array)array_diff($inventoryRecordId, $ids));  //去掉仓位下对应的id
            }
        }
        $res = update([
            "table" => 'warehouse_position',
            "field" => ['inventoryRecordId' => trim(implode(',', $inventoryRecordId), ",")],
            "where" => "id = '$warehouse_position[id]'",
        ]);
        if ($res != '更新成功') {
            $warn = $res;
        }
        resp:
        return $warn;
    }

    /**
     * 期初数量
     *
     * @param string $materialId
     * @param string $warehouseId
     * @param string $date
     * @return float
     */
    public static function inventoryDefaultNum(string $materialId, string $warehouseId = '', string $orderDate = ''): float
    {
        $where = [
            'materialId' => $materialId,
            'coid'       => self::$coid,
        ];
        if ($warehouseId) {
            $where['warehouseId'] = $warehouseId;
        }
        $and = '';
        if ($orderDate) {
            $data       = explode('~', $orderDate);
            $startStamp = strtotime(trim($data[0]));
            $and        = " AND date_format(`time`, '%Y-%m-%d') < '" . date('Y-m-d', $startStamp) . '\'';
        }
        return static::total([
            'sql'   => 'SELECT IFNULL(sum(num), 0) as total FROM `inventory_record` ',
            'where' => generateWhere($where) . $and,
        ]);
    }

    /**
     * 待检数量
     *
     * @param string $materialId
     * @param string $warehouseId
     * @return float
     */
    public static function pendingCheck(string $materialId, string $warehouseId = ''): float
    {
        $and   = " and qo.type not in (6,3,4)";
        $where = [
            'qo.materialId' => $materialId,
            'qo.state'      => '待质检',
        ];
        if ($warehouseId) {
            $and .= $warehouseId;
        }
        $res = find([
            'field'  => ' ifnull(SUM(CASE WHEN qo.unit = mat.unit_one THEN qo.num*mat.unit_one_num WHEN qo.unit = mat.unit_two THEN qo.num*mat.unit_two_num ELSE qo.num END),0) AS num',
            'table'  => 'quality_order as qo join material as mat on qo.materialId = mat.id',
            'single' => generateWhere($where) . $and,
        ]);
        return $res['num'];
    }

    /**
     * 不良数量
     *
     * @param string $materialId
     * @param string $warehouseId
     * @return float
     */
    public static function unhealthy(string $materialId, string $unit, string $warehouseWhere = ''): float
    {
        $where    = generateWhere([
            'q.coid'       => self::$coid,
            'q.state'      => '已质检',
            'q.materialId' => $materialId,
            'r.state'      => '待处理',
        ]);
        $where    .= $warehouseWhere ?: '';
        $scrapNum      = find([
            'table' => 'quality_order as q, quality_order_reason as r, material as mat',
            'single' => " q.type <> 3 AND q.id = r.orderId and q.materialId = mat.id AND $where ",
            'field' => " ifnull(SUM(CASE WHEN q.unit = mat.unit_one THEN r.num*mat.unit_one_num WHEN q.unit = mat.unit_two THEN r.num*mat.unit_two_num ELSE r.num END),0) AS num ",
        ]);
        return $scrapNum['num'];
    }

    /**
     * 物料单位
     *
     * @param $materialId
     * @return array
     */
    public static function materialUnit(string $materialId): array
    {
        $material = query('material', " id = '$materialId' AND coid = '" . self::$coid . "' ");
        if (!static::isNull($material)) {
            return self::filterArray([$material['unit'], $material['unit_one'], $material['unit_two']]);
        } else {
            return explode('，', para('materialUnit'));
        }
    }

    /**
     * 转换为主单位数量
     *
     * @param $materialId
     * @param $num
     * @param $nowUnit
     * @return float|int
     */
    public static function toMainUnit(string $materialId, float $num, string $nowUnit = ''): float|int
    {
        $material = query('material', " id = '$materialId' ");
        $nowUnit  = $nowUnit ?: $material['unit'];
        return machiningOrderClass::material_num_change($materialId, $nowUnit, $material['unit'], $num);
    }

    /**
     * 补出入库单据
     *
     * @param $table
     * @param $id
     * @return void
     */
    public static function otherToinventory($table, $id)
    {
        if (!in_array($table, ['inventory_allot', 'inventory_transfer', 'inventory_dismantle', 'inventory_assembly'])) {
            return;
        }
        if (in_array($table, ['inventory_allot', 'inventory_dismantle', 'inventory_assembly'])) {
            $info   = query($table, " id = '$id' ");
            $result = self::sqlFind("SELECT * FROM `{$table}_detail` WHERE orderId = '$id' ");
            $field  = [
                'coid'        => self::$coid,
                'orderDate'   => date('Y-m-d'),
                'sourceTable' => $table,
                'sourceId'    => $id,
                'commitTime'  => date('Y-m-d H:i:s'),
                'confirmTime' => date('Y-m-d H:i:s'),
                'stid'        => self::$stid,
            ];
        } else {
            $result = self::sqlFind("SELECT * FROM `inventory_transfer` WHERE id in ('" . implode("','", (array)$id) . "') ");
        }
        $inId        = self::getId();
        $inChangeId  = self::getId();
        $outId       = self::getId();
        $outChangeId = self::getId();
        switch ($table) {
            // 调拨
            case 'inventory_allot':
                $inField        = [
                    'id'          => $inId,
                    'orderNo'     => codeTemplateClass::generateCode('inStockOther', [
                        'prefix' => 'DBRK' . date('Ymd'),
                        'table'  => self::tableInv,
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '调拨单入库',
                    'classify'    => 1,
                    'warehouseId' => $info['inWarehouseId'],
                    'state'       => '已入库',
                    'text'        => '调拨单入库，ID' . $id,
                    'orderDate'   => date('Y-m-d'),
                    'sourceDate'  => $info['orderDate'],
                    'sourceNo'    => $info['orderNo'],
                ];
                $inChangeField  = [
                    'id'          => $inChangeId,
                    'coid'        => self::$coid,
                    'orderNo'     => codeTemplateClass::generateCode('inStock', [
                        'prefix' => 'RKD' . date('Ymd'),
                        'table'  => 'inventory_changes',
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '调拨单入库',
                    'classify'    => 1,
                    'confirmTime' => date("Y-m-d H:i:s"),
                    'reviewTime'  => date("Y-m-d H:i:s"),
                    'state'       => '已复核',
                    'stid'        => self::$stid,
                    'text'        => '调拨单入库，ID' . $id,
                ];
                $outField       = [
                    'id'          => $outId,
                    'orderNo'     => codeTemplateClass::generateCode('outStockOther', [
                        'prefix' => 'DBCK' . date('Ymd'),
                        'table'  => self::tableInv,
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '调拨单出库',
                    'classify'    => 0,
                    'warehouseId' => $info['outWarehouseId'],
                    'state'       => '已出库',
                    'text'        => '调拨单出库，ID' . $id,
                    'orderDate'   => date('Y-m-d'),
                    'sourceDate'  => $info['orderDate'],
                    'sourceNo'    => $info['orderNo'],
                ];
                $outChangeField = [
                    'id'          => $outChangeId,
                    'coid'        => self::$coid,
                    'orderNo'     => codeTemplateClass::generateCode('outStock', [
                        'prefix' => 'RKD' . date('Ymd'),
                        'table'  => 'inventory_changes',
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '调拨单出库',
                    'classify'    => 0,
                    'confirmTime' => date("Y-m-d H:i:s"),
                    'reviewTime'  => date("Y-m-d H:i:s"),
                    'state'       => '已复核',
                    'stid'        => self::$stid,
                    'text'        => '调拨单出库，ID' . $id,
                ];
                static::insert(["table" => self::tableInv, "field" => array_merge($field, $inField)]);
                static::insert(["table" => 'inventory_changes', "field" => $inChangeField]);
                static::insert(["table" => self::tableInv, "field" => array_merge($field, $outField)]);
                static::insert(["table" => 'inventory_changes', "field" => $outChangeField]);
                if ($info) {
                    foreach ($result as $array) {
                        $inMxId        = self::getId();
                        $inChangeMxId  = self::getId();
                        $outMxId       = self::getId();
                        $outChangeMxId = self::getId();
                        $mxField       = [
                            'coid'        => self::$coid,
                            'materialId'  => $array['materialId'],
                            'batch'       => $array['batch'],
                            'num'         => $array['num'],
                            'price'       => $array['price'],
                            'unit'        => $array['unit'],
                            'money'       => self::formattingFigure($array['num'] * $array['price']),
                            'sourceTable' => $table . '_detail',
                            'sourceId'    => $array['id'],
                            'text'        => '调拨单子表ID：' . $array['id'],
                        ];
                        $mxChangeField = [
                            'coid'       => self::$coid,
                            'materialId' => $array['materialId'],
                            'orderNum'   => $array['num'],
                            'batch'      => $array['batch'],
                            'num'        => $array['num'],
                            'unit'       => $array['unit'],
                            'price'      => $array['price'],
                            'text'       => '调拨单子表ID：' . $array['id'],
                        ];

                        // 出库
                        static::insert(["table" => self::tableInvMx, "field" => array_merge($mxField, ['id' => $outMxId, 'orderId' => $outId, 'warehouseId' => $info['outWarehouseId'],]),]);
                        static::insert(["table" => 'inventory_changes_detail', "field" => array_merge($mxChangeField, ['id' => $outChangeMxId, 'orderId' => $outChangeId, 'sourceTable' => 'inventory_detail', 'sourceId' => $outMxId, 'sourceNo' => $outField['orderNo'], 'warehouseId' => $info['outWarehouseId'],]),]);
                        static::update(["table" => 'inventory_record', "field" => ['inventoryId' => $outId, 'inventoryMxId' => $outMxId, 'moveId' => '', 'changesId' => $outChangeMxId, 'defaultPrice' => $array['price']], "where" => "moveId = '$info[id]' and batch = '" . $array['batch'] . "' and num < 0 and coid = '" . self::$coid . "' and materialId = '" . $array['materialId'] . "'",]);
                        // 入库
                        static::insert(["table" => self::tableInvMx, "field" => array_merge($mxField, ['id' => $inMxId, 'orderId' => $inId, 'warehouseId' => $info['inWarehouseId'],]),]);
                        static::insert(["table" => 'inventory_changes_detail', "field" => array_merge($mxChangeField, ['id' => $inChangeMxId, 'orderId' => $inChangeId, 'sourceTable' => 'inventory_detail', 'sourceId' => $inMxId, 'sourceNo' => $inField['orderNo'], 'warehouseId' => $info['inWarehouseId'],]),]);
                        static::update(["table" => 'inventory_record', "field" => ['inventoryId' => $inId, 'inventoryMxId' => $inMxId, 'moveId' => '', 'changesId' => $inChangeMxId, 'defaultPrice' => $array['price']], "where" => "moveId = '$info[id]' and batch = '" . $array['batch'] . "' and num > 0 and coid = '" . self::$coid . "' and materialId = '" . $array['materialId'] . "'",]);
                    }
                }
                break;
            // 移库
            case 'inventory_transfer':
                $inChangeField  = [
                    'id'          => $inChangeId,
                    'coid'        => self::$coid,
                    'orderNo'     => codeTemplateClass::generateCode('inStock', [
                        'prefix' => 'RKD' . date('Ymd'),
                        'table'  => 'inventory_changes',
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '移库入库',
                    'classify'    => 1,
                    'confirmTime' => date("Y-m-d H:i:s"),
                    'reviewTime'  => date("Y-m-d H:i:s"),
                    'state'       => '已复核',
                    'stid'        => self::$stid,
                    'text'        => '移库入库，ID' . implode(',', $id),
                ];
                $outChangeField = [
                    'id'          => $outChangeId,
                    'coid'        => self::$coid,
                    'orderNo'     => codeTemplateClass::generateCode('outStock', [
                        'prefix' => 'RKD' . date('Ymd'),
                        'table'  => 'inventory_changes',
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '移库出库',
                    'classify'    => 0,
                    'confirmTime' => date("Y-m-d H:i:s"),
                    'reviewTime'  => date("Y-m-d H:i:s"),
                    'state'       => '已复核',
                    'stid'        => self::$stid,
                    'text'        => '移库出库，ID' . implode(',', $id),
                ];
                static::insert(["table" => 'inventory_changes', "field" => $inChangeField]);
                static::insert(["table" => 'inventory_changes', "field" => $outChangeField]);
                foreach ($result as $array) {
                    $material      = query('material', " id = '" . $array['materialId'] . "'", 'unit');
                    $inChangeMxId  = self::getId();
                    $outChangeMxId = self::getId();
                    $mxChangeField = [
                        'coid'       => self::$coid,
                        'materialId' => $array['materialId'],
                        'orderNum'   => $array['num'],
                        'batch'      => $array['batch'],
                        'num'        => $array['num'],
                        'unit'       => $material['unit'],
                        'price'      => inventoryBalanceClass::unitPrice($array['materialId']),
                        'text'       => '移库单子表ID：' . $array['id'],
                    ];
                    // 出库
                    static::insert(["table" => 'inventory_changes_detail', "field" => array_merge($mxChangeField, ['id' => $outChangeMxId, 'orderId' => $outChangeId, 'sourceTable' => '', 'sourceId' => '', 'sourceNo' => '', 'warehouseId' => $array['warehouseId'], 'positionId' => $array['positionId']]),]);
                    static::update(["table" => 'inventory_record', "field" => ['changesId' => $outChangeMxId], "where" => "moveId = '$array[id]' and batch = '" . $array['batch'] . "' and num < 0 and coid = '" . self::$coid . "' and materialId = '" . $array['materialId'] . "'",]);
                    // 入库
                    static::insert(["table" => 'inventory_changes_detail', "field" => array_merge($mxChangeField, ['id' => $inChangeMxId, 'orderId' => $inChangeId, 'sourceTable' => '', 'sourceId' => '', 'sourceNo' => '', 'warehouseId' => $array['inWarehouseId'], 'positionId' => $array['inLocationId']]),]);
                    static::update(["table" => 'inventory_record', "field" => ['changesId' => $inChangeMxId], "where" => "moveId = '$array[id]' and batch = '" . $array['batch'] . "' and num > 0 and coid = '" . self::$coid . "' and materialId = '" . $array['materialId'] . "'",]);
                }
                break;
            case 'inventory_dismantle':
                // 拆解
                $inField  = [
                    'id'          => $inId,
                    'orderNo'     => codeTemplateClass::generateCode('inStockOther', [
                        'prefix' => 'CJRK' . date('Ymd'),
                        'table'  => self::tableInv,
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '拆解单入库',
                    'classify'    => 1,
                    'warehouseId' => '0000',
                    'state'       => '已入库',
                    'text'        => '拆解入库，ID' . $id,
                    'orderDate'   => date('Y-m-d'),
                    'sourceDate'  => $info['orderDate'],
                    'sourceNo'    => $info['orderNo'],
                ];
                $outField = [
                    'id'          => $outId,
                    'orderNo'     => codeTemplateClass::generateCode('outStockOther', [
                        'prefix' => 'CJCK' . date('Ymd'),
                        'table'  => self::tableInv,
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '拆解单出库',
                    'classify'    => 0,
                    'warehouseId' => $info['warehouseId'],
                    'state'       => '已出库',
                    'text'        => '拆解出库，ID' . $id,
                    'orderDate'   => date('Y-m-d'),
                    'sourceDate'  => $info['orderDate'],
                    'sourceNo'    => $info['orderNo'],
                ];
                static::insert(["table" => self::tableInv, "field" => array_merge($field, $inField)]);
                static::insert(["table" => self::tableInv, "field" => array_merge($field, $outField)]);
                // 出库
                $outMxId = self::getId();
                static::insert([
                    "table" => self::tableInvMx, "field" => [
                        'id'          => $outMxId,
                        'coid'        => self::$coid,
                        'materialId'  => $info['materialId'],
                        'num'         => $info['num'],
                        'price'       => $info['inventoryPrice'],
                        'unit'        => self::materialUnit($info['materialId'])[0],
                        'money'       => self::formattingFigure($info['num'] * $info['inventoryPrice']),
                        'text'        => '拆解单ID：' . $info['id'],
                        'orderId'     => $outId,
                        'warehouseId' => $info['warehouseId'],

                    ],
                ]);
                static::update(["table" => 'inventory_record', "field" => ['inventoryId' => $outId, 'inventoryMxId' => $outMxId, 'moveId' => ''], "where" => "moveId = '$info[id]' and num < 0",]);
                if ($info) {
                    foreach ($result as $array) {
                        // 子件入库单价（金额+拆解费用分摊）/入库数量
                        $price   = $array['price'];
                        $mxField = [
                            'id' => self::getId(),

                            'coid'        => self::$coid,
                            'materialId'  => $array['materialId'],
                            'num'         => $array['num'],
                            'price'       => $price,
                            'unit'        => $array['unit'],
                            'sourceTable' => $table . '_detail',
                            'sourceId'    => $array['id'],
                            'money'       => self::formattingFigure($array['num'] * $price),
                            'text'        => '拆解单子表ID：' . $array['id'],
                        ];
                        // 入库
                        static::insert(["table" => self::tableInvMx, "field" => array_merge($mxField, ['orderId' => $inId, 'warehouseId' => $info['warehouseId'],])]);
                        static::update(["table" => 'inventory_record', "field" => ['inventoryId' => $inId, 'inventoryMxId' => $mxField['id'], 'moveId' => ''], "where" => "moveId = '$info[id]' and num > 0 and coid = '" . self::$coid . "' and materialId = '" . $array['materialId'] . "'",]);
                    }
                }
                break;
            case 'inventory_assembly':
                // 组装
                $inField  = [
                    'id'          => $inId,
                    'orderNo'     => codeTemplateClass::generateCode('inStockOther', [
                        'prefix' => 'ZZCK' . date('Ymd'),
                        'table'  => self::tableInv,
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '组装单入库',
                    'classify'    => 1,
                    'warehouseId' => '0000',
                    'state'       => '已入库',
                    'text'        => '组装入库，ID' . $id,
                    'orderDate'   => date('Y-m-d'),
                    'sourceDate'  => $info['orderDate'],
                    'sourceNo'    => $info['orderNo'],
                ];
                $outField = [
                    'id'          => $outId,
                    'orderNo'     => codeTemplateClass::generateCode('outStockOther', [
                        'prefix' => 'ZZCK' . date('Ymd'),
                        'table'  => self::tableInv,
                        'field'  => 'orderNo',
                        'where'  => " AND coid = '" . self::$coid . "' ",
                    ], []),
                    'type'        => '组装单出库',
                    'classify'    => 0,
                    'warehouseId' => $info['warehouseId'],
                    'state'       => '已出库',
                    'text'        => '组装出库，ID' . $id,
                    'orderDate'   => date('Y-m-d'),
                    'sourceDate'  => $info['orderDate'],
                    'sourceNo'    => $info['orderNo'],
                ];
                static::insert(["table" => self::tableInv, "field" => array_merge($field, $inField)]);
                static::insert(["table" => self::tableInv, "field" => array_merge($field, $outField)]);
                // 入库
                //$assemblyCost = self::assemblyCost($info['id']);
                $inMxId = self::getId();
                static::insert([
                    "table" => self::tableInvMx, "field" => [
                        'id'          => $inMxId,
                        'coid'        => self::$coid,
                        'orderId'     => $inId,
                        'warehouseId' => $info['warehouseId'],
                        'materialId'  => $info['materialId'],
                        'num'         => $info['num'],
                        'sourceTable' => $table . '_detail',
                        'sourceId'    => $info['id'],
                        'price'       => $info['inventoryPrice'],
                        'unit'        => self::materialUnit($info['materialId'])[0],
                        'money'       => self::formattingFigure($info['inventoryPrice'] * $info['num']),
                        'text'        => '组装单ID：' . $info['id'],
                    ],
                ]);
                static::update(["table" => 'inventory_record', "field" => ['inventoryId' => $inId, 'inventoryMxId' => $inMxId, 'moveId' => ''], "where" => "moveId = '$info[id]' and num > 0",]);
                if ($info) {
                    foreach ($result as $array) {
                        $outMxId = self::getId();
                        $mxField = [
                            'id'          => $outMxId,
                            'coid'        => self::$coid,
                            'materialId'  => $array['materialId'],
                            'num'         => $array['num'],
                            'price'       => $array['price'],
                            'unit'        => $array['unit'],
                            'sourceTable' => $table . '_detail',
                            'sourceId'    => $array['id'],
                            'money'       => self::formattingFigure($array['num'] * $array['price']),
                            'text'        => '组装单子表ID：' . $array['id'],
                        ];
                        // 出库
                        static::insert(["table" => self::tableInvMx, "field" => array_merge($mxField, ['orderId' => $outId, 'warehouseId' => $array['warehouseId'],])]);
                        static::update(["table" => 'inventory_record', "field" => ['inventoryId' => $outId, 'inventoryMxId' => $outMxId, 'moveId' => ''], "where" => "moveId = '$info[id]' and num < 0 and coid = '" . self::$coid . "' and materialId = '" . $array['materialId'] . "'",]);
                    }
                }
                break;
        }
    }

    /**
     * 组装件成本
     *
     * @param string $id
     * @return array  assemblyCost 组装成本; cost 子件成本; avg 组装件入库单价
     */
    public static function assemblyCost(string $id): array
    {
        $res['cost'] = $res['avg'] = $res['assemblyCost'] = 0;
        $info        = query('inventory_assembly', " id = '$id' ");
        if (!empty($info['id'])) {
            $assemblyFee         = $info['fee'];
            $res['assemblyCost'] = round(static::total([
                'sql'   => "SELECT IFNULL(SUM(num*price),0) as total FROM `inventory_assembly_detail` ",
                'where' => [
                    'orderId' => $info['id'],
                ],
            ]), 2);
            $res['cost']         = self::formattingFigure($res['assemblyCost'] + $assemblyFee);
            $res['avg']          = empty($info['num']) ? 0 : self::formattingFigure(($res['assemblyCost'] + $assemblyFee) / $info['num'], 'pricePrecision');
        }
        return $res;
    }

    /**
     * 导出模板字段初始化
     * @return array[]
     */
    public function exportFieldInit($classify = ''): array
    {
        return match ($classify) {
            default => [
                [
                    'columnName' => '物料编码',
                    'aliasName'  => '物料编码',
                ],
                [
                    'columnName' => '物料名称',
                    'aliasName'  => '物料名称',
                ],
                [
                    'columnName' => '物料分类',
                    'aliasName'  => '物料分类',
                ],
                [
                    'columnName' => '规格型号',
                    'aliasName'  => '规格型号',
                ],
                [
                    'columnName' => '主单位',
                    'aliasName'  => '主单位',
                ],
                [
                    'columnName' => '主单位数量',
                    'aliasName'  => '主单位数量',
                ],
                [
                    'columnName' => '待检数量',
                    'aliasName'  => '待检数量',
                ],
                [
                    'columnName' => '不良数量',
                    'aliasName'  => '不良数量',
                ],
                [
                    'columnName' => '辅单位1',
                    'aliasName'  => '辅单位1',
                ],
                [
                    'columnName' => '辅单位1数量',
                    'aliasName'  => '辅单位1数量',
                ],
                [
                    'columnName' => '辅单位2',
                    'aliasName'  => '辅单位2',
                ],
                [
                    'columnName' => '辅单位2数量',
                    'aliasName'  => '辅单位2数量',
                ],
                [
                    'columnName' => '单价',
                    'aliasName'  => '单价（元）',
                ],
                [
                    'columnName' => '金额',
                    'aliasName'  => '金额（元）',
                ],
                [
                    'columnName' => '库存预警',
                    'aliasName'  => '库存预警',
                ],
            ]
        };
    }
}
